In [ ]:
import numpy as np
from menpo.transform import Rotation, Scale, Translation

In [ ]:
rotation = np.array([[ 0.36,  0.48, -0.80],
                     [-0.80,  0.60,  0.00],
                     [ 0.48,  0.64,  0.60]])
scale = np.array([7,3, 15])
scale2 = np.ones(3)*-3.52
translation = np.array([-1,20])

In [ ]:
r = Rotation(rotation)
nus = Scale(scale)           # NonUniformScale (Affine)
us = Scale(2, n_dims=3)      # UniformScale (Similarity)
t = Translation(translation)

All affine transforms are printable. You will see the usual homogeneous matrix, and an English decription of what the affine transform does


In [ ]:
print r

In [ ]:
print nus

In [ ]:
print t

All these are instances of DiscreteAffineTransform. That means we can ask any of these to invert themselves


In [ ]:
print us
print us.pseudoinverse

All affine transforms can be chained together using the chain(another_affine_transform) method. This produces a new AffineTransform. Note that printing a general affine transform describes an equalivilent set of discrete affine transforms (that is, a sequence of discrete Rotation, Translation and Scale operations) that perform the same transform


In [ ]:
rotation_followed_by_scale = r.compose_before(nus)
print rotation_followed_by_scale

We can request this sequence directly by using the decompose() method
notice how all affine transforms support eqality checking


In [ ]:
decomposed = rotation_followed_by_scale.decompose() 
result_of_chain = reduce(lambda x, y: x.compose_before(y), decomposed)
print result_of_chain
print 'Does chaining the decomposition do the same as the original? %s' % (result_of_chain == rotation_followed_by_scale)

Note that chaining SimilarityTransform objects together yields a SimilarityTransform instead.


In [ ]:
print r.compose_before(us)

Finally, note that all instances of Transform are guaranteed to have an .apply() method. Novel points can be passed in here, which will then be transformed (the result is returned, and the points left as they are). However, objects passed into apply() can define a ._transform() method, signifing that this object knows how to handle it's own transformation. In this case, the trasformation is applied in place. PointCloud is one such class that defines this method.


In [ ]:
%matplotlib inline
from menpo.shape import PointCloud
points = np.array([[0.0, 0.0],
                   [1.0, 0.0],
                   [1.0, 1.0],
                   [0.0, 1.0]])
pc = PointCloud(points)
print pc
print pc.points
pc.view()

A transform can .apply() to some raw points to yield new ones...


In [ ]:
import matplotlib.pyplot as plt
new_points = t.apply(points)
print new_points
plt.scatter(new_points[:, 0], new_points[:, 1])

..or can apply directly to Transformable objects.


In [ ]:
pc3 = t.apply(pc)
print pc3.points
pc3.view()